package application.messager;

import application.anno.MessageActions;
import application.anno.impl.AutoRegisterImpl;
import application.exception.NotFoundNecessaryAnnotationException;
import application.util.ReflectionsUtil;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public abstract class MessageReceiver {

    private Set<String> actions;

    public MessageReceiver() {
        actions = new HashSet<>();
        try {
            init();
        } catch (NotFoundNecessaryAnnotationException e) {
            e.printStackTrace();
        }
    }

    private void init() throws NotFoundNecessaryAnnotationException {
        AutoRegisterImpl autoRegister = new AutoRegisterImpl();
        MessageActions declaredAnnotation = this.getClass().getDeclaredAnnotation(MessageActions.class);
        if (declaredAnnotation != null) {
            autoRegister.registerInMessageReceiver(this);
        } else {
            List<Method> methods = Arrays.asList(this.getClass().getDeclaredMethods());
            Set<Method> annotationByMethod = ReflectionsUtil.getAnnotationByMethod(MessageActions.class);
            annotationByMethod.retainAll(methods);
            for (Method method : annotationByMethod) {
                MessageActions actions = method.getDeclaredAnnotation(MessageActions.class);
                for (String action : actions.actions()) {
                    this.addAction(action);
                }
            }
            this.register();
        }
    }

    public abstract boolean receive(Messager messager);

    public boolean hasAction() {
        return !this.actions.isEmpty();
    }

    public boolean isExist(String action) {
        return this.actions.contains(action);
    }

    // 注册接收者
    public void register() {
        MessageCenter.getInstance().register(this);
    }

    // 注销接收者
    public void unregister() {
        MessageCenter.getInstance().unregister(this);
    }

    // 注册监听动作
    public void addAction(String action) {
        this.actions.add(action);
    }
}
